/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.editpart;

import java.util.Iterator;
import java.util.List;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.editpolicies.ContainerEditPolicy;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gef.requests.GroupRequest;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Pseudostate;
import org.eclipse.uml2.uml.State;
import org.eclipse.uml2.uml.StateMachine;

import com.cea.papyrus.core.commands.GraphNodeDeleteCommand;
import com.cea.papyrus.core.commands.GraphNodeDeleteWithSemanticParentCommand;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagraminterchange2.di2.DiagramElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * This editpolicy has in charge to delete before adding in new container
 */
public class ContainerWithSemanticEditPolicy extends ContainerEditPolicy {

	/**
	 * Debug channel.
	 */
	protected static final int channel=22;

	/**
	 * {@inheritDoc}
	 */
	protected Command getCreateCommand(CreateRequest request) {
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected Command getOrphanChildrenCommand(GroupRequest request) {
		Debug.debug(this, "CreateOrphanCommand", channel);
		List parts =request.getEditParts();

		//0. prepare the command
		CompoundCommand c= new CompoundCommand();

		for (int i = 0; i < parts.size(); i++) {
			//get the graphNode
			GraphElement gChild=(GraphElement)((EditPart)parts.get(i)).getModel();
			//if the graphnode has semantic child
			c.add(createCommand(gChild));
		}
		Debug.debug(this, "End of CreateOrphanCommand", channel);
		return c.unwrap();
	}

 // this code is like DiagramElementDeleteCommandFactory witout suppressing links
	/**
	 * create command to remove a node with semantic without links
	 * @param node to remove
	 * @return set of commands
	 */
	protected Command createCommandWithSemanticParent(GraphNode node) {
		CompoundCommand command = new CompoundCommand();
		GraphElement parent;
		GraphElement semancticParent;
		// in the case of a semanticmodel we look for the helper
			//no helper --> basic helper
			parent=node.getContainer();
			semancticParent=(GraphElement)node.getSemanticParent();
	

		//delete indirect subnodes
		Iterator<DiagramElement> it=node.getSemanticChild().iterator();
		while (it.hasNext()){
			GraphElement ge=(GraphElement)it.next();
			if(ge instanceof GraphNode){
			command.add(createCommand((GraphElement)ge));}
		}
		command.add(new GraphNodeDeleteWithSemanticParentCommand(parent, node,semancticParent));

		return command;


	}
/**
 * prepare command to supress a node that has not semantic without links
 * @param node to suppres
 * @return the set of command
 */
	public Command createCommand(GraphNode node) {
		CompoundCommand command = new CompoundCommand();

		GraphElement parent = node.getContainer();
		//delete indirect subnodes
		
		//avoid the case of statemachine because semantic child list is used 
		//to store the list of regions
		if(node.getSemanticModel()!=null){
			if(((Uml1SemanticModelBridge)node.getSemanticModel()).getElement()!=null){
				Element elt = ((Uml1SemanticModelBridge)node.getSemanticModel()).getElement();
				
				
				if(!(elt instanceof StateMachine)
						&& !((elt instanceof State) && ((State)elt).isComposite())){
					Iterator<DiagramElement> it=node.getSemanticChild().iterator();
					while (it.hasNext()){
						GraphElement ge=(GraphElement)it.next();
						command.add(createCommand(ge));
					}
				}
				//get rid of the pseudostates only for statemachines and composite states
				else{
					Iterator<DiagramElement> it=node.getSemanticChild().iterator();
					while (it.hasNext()){
						GraphElement ge=(GraphElement)it.next();
						if((ge.getSemanticModel() != null) && (((Uml1SemanticModelBridge)ge.getSemanticModel()).getElement() instanceof Pseudostate))
							command.add(createCommand(ge));
					}
				}
			}
		}

		command.add(new GraphNodeDeleteCommand(parent, node));
		return command;
	}
	
	/**
	 * this method choose the good method to choose for a node 
	 * @param elementthe Graphelement that we want to supress
	 * @return the set of command
	 */
	public Command createCommand(GraphElement element) {
		CompoundCommand command = new CompoundCommand(); 
		if (element instanceof GraphNode) {
			if(element.getSemanticParent()!=null){
				command.add(createCommandWithSemanticParent((GraphNode)element));
			}
			else{
				command.add(createCommand((GraphNode) element));
			}
		}
		return command;
	}
	
	
}